package org.apogee.mil.server.greeting;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import org.apache.log4j.Logger;
import org.apogee.mil.client.services.greeting.GreetingService;
import org.apogee.mil.server.database.DatabaseDriver;
import org.apogee.mil.server.database.helper.DatabaseConnector;
import org.apogee.mil.server.database.helper.DatabaseQueries;
import org.apogee.mil.shared.Constants.DisplayFormat;
import org.apogee.mil.shared.Constants.MessagesField;
import org.apogee.mil.shared.Constants.ServerConfigFields;
import org.apogee.mil.shared.Constants.UserLookupFields;
import org.apogee.mil.shared.ServerConfig;

import com.extjs.gxt.ui.client.data.BaseModel;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
	private static Logger logger = Logger.getLogger(GreetingServiceImpl.class);

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private DatabaseDriver db;
	
	@Override
	public boolean initialize() {
		db = new DatabaseDriver();
		return db.initialize();
	}

	@Override
	public ArrayList<BaseModel> getServerConfig() throws Exception {
		ArrayList<BaseModel> results = new ArrayList<BaseModel>();

		String stmt = String.format(DatabaseQueries.SERVER_CONFIG_ALL_QRY, ServerConfigFields.PROPERTY, ServerConfigFields.VALUE);

		ResultSet set = db.executeQuery(stmt);

		while(set.next()) {
			BaseModel bm = new BaseModel();
			bm.set(ServerConfigFields.PROPERTY, set.getString(ServerConfigFields.PROPERTY));
			bm.set(ServerConfigFields.VALUE, set.getString(ServerConfigFields.VALUE));

			results.add(bm);
		}

		return results;
	}

	@Override
	public ArrayList<BaseModel> getServerInfo() {

		ArrayList<BaseModel> info = new ArrayList<BaseModel>();

		String serverInfo = getServletContext().getServerInfo();
		String userAgent = getThreadLocalRequest().getHeader("User-Agent");
		String serverType = "Unknown";
		String buildNum = "Unknown";
		String buildDate = "Unknown";

		if (db == null) {
			initialize();
		}
		String dbInfo = db.getDataBaseInfo();
		String os = System.getProperty("os.name") == null ? "Unknown" : System.getProperty("os.name");
		String jvmVersion = System.getProperty("java.version") == null ? "Unknown" : System.getProperty("java.version");

		String stmt = String.format(DatabaseQueries.SERVER_CONFIG_QRY, ServerConfigFields.PROPERTY,
				ServerConfigFields.VALUE, ServerConfigFields.PROPERTY, "Server Type");

		ResultSet set = db.executeQuery(stmt);

		try {
			if (set.next()) {
				serverType = set.getString(ServerConfigFields.VALUE);
				ServerConfig.SERVER_TYPE = serverType;
			} 
		} catch (SQLException e) { }


		stmt = String.format(DatabaseQueries.SERVER_CONFIG_QRY, ServerConfigFields.PROPERTY,
				ServerConfigFields.VALUE, ServerConfigFields.PROPERTY, "Server Build");

		set = db.executeQuery(stmt);		

		try {
			if (set.next()) {
				buildNum = set.getString(ServerConfigFields.VALUE);
				ServerConfig.SERVER_BUILD = Integer.parseInt(buildNum);
			} 
		} catch (Exception e) { }

		stmt = String.format(DatabaseQueries.SERVER_CONFIG_QRY, ServerConfigFields.PROPERTY,
				ServerConfigFields.VALUE, ServerConfigFields.PROPERTY, "Build Date");

		set = db.executeQuery(stmt);		

		try {
			if (set.next()) {
				buildDate = set.getString(ServerConfigFields.VALUE);
				ServerConfig.BUILD_DATE = Integer.parseInt(buildDate);
			} 
		} catch (Exception e) { }

		
		stmt = String.format(DatabaseQueries.SERVER_CONFIG_QRY, ServerConfigFields.PROPERTY,
				ServerConfigFields.VALUE, ServerConfigFields.PROPERTY, "Debug Enabled");
		
		set = db.executeQuery(stmt);
		
		try {
			if (set.next()) {
				String debug = set.getString(ServerConfigFields.VALUE);
				ServerConfig.DEBUG = Boolean.parseBoolean(debug);
			}
		} catch (Exception e) { }
		

		BaseModel bm = new BaseModel();
		bm.set("heading", "Web Version");
		bm.set("val", String.format("%s.%s %s", buildDate, buildNum, "Beta"));

		info.add(bm);

		bm = new BaseModel();
		bm.set("heading", "Web Server");
		bm.set("val", String.format("%s [%s]", serverInfo, serverType.toUpperCase()));

		info.add(bm);

		bm = new BaseModel();
		bm.set("heading", "Web Server OS");
		bm.set("val", os);

		info.add(bm);

		bm = new BaseModel();
		bm.set("heading", "Web Client");
		bm.set("val", userAgent);

		info.add(bm);

		bm = new BaseModel();
		bm.set("heading", "Database");
		bm.set("val", dbInfo);

		info.add(bm);

		bm = new BaseModel();
		bm.set("heading", "Java Version");
		bm.set("val", jvmVersion);

		info.add(bm);
		if (serverType.toLowerCase().contains("test")) {
			String jbossBase = System.getProperty("jboss.server.base.dir") == null ? "" : System.getProperty("jboss.server.base.dir");
			String tomcatBase = System.getProperty("catalina.base") == null ? "" : System.getProperty("catalina.base");

			bm = new BaseModel();
			bm.set("heading", "Jboss Base Dir");
			bm.set("val", jbossBase);

			info.add(bm);

			bm = new BaseModel();
			bm.set("heading", "Tomcat Base Dir");
			bm.set("val", tomcatBase);

			info.add(bm);

		}
		return info;
	}



	@Override
	public ArrayList<BaseModel> getMessages(int toUserId) {
		String stmt = String.format(DatabaseQueries.MESSAGE_QRY, UserLookupFields.FIRST_NAME, UserLookupFields.LAST_NAME, MessagesField.MESSAGE,
				MessagesField.DATE, MessagesField.DATE, UserLookupFields.USER_ID, MessagesField.FROM_USER_ID,
				MessagesField.TO_USER_ID, toUserId, MessagesField.DATE);

		ArrayList<BaseModel> results = new ArrayList<BaseModel>();

		ResultSet set = db.executeQuery(stmt);

		try {
			while (set.next()) {

				String userFmt = set.getString(UserLookupFields.FIRST_NAME) + " " + set.getString(UserLookupFields.LAST_NAME);
				String date = set.getString(MessagesField.DATE);
				String msg = set.getString(MessagesField.MESSAGE);

				BaseModel bm = new BaseModel();
				bm.set(DisplayFormat.USER_FMT, userFmt);
				bm.set(MessagesField.DATE, date);
				bm.set(MessagesField.MESSAGE, msg);

				results.add(bm);
			}
		} catch (SQLException ex) {
			logger.error("Unable to retreive messages: " + ex.getMessage());
		}

		return results;
	}

	@Override
	public boolean loadConfig() throws Exception {
		String base = getBase();
		
		if (base == null) {
			return false;
		}
		
		String context = getServletContext().getContextPath();
		
		String confStr = base +"/configuration/" + context + ".properties";
		
		File confFile = new File(confStr);
		
		if (confFile.exists() == false) {
			return false;
		}
		
		FileReader reader = new FileReader(confFile);
		
		BufferedReader bReader = new BufferedReader(reader);
		
		while (bReader.ready()) {
			String line = bReader.readLine();
			
			if (line.startsWith("#")) continue;
			
			String[] values = line.split("=");
			
			if (values.length != 2) continue;
			
			DatabaseConnector.getDatabaseInfo().put(values[0], values[1]);
		}
		
		bReader.close();
		if (DatabaseConnector.getDatabaseInfo().size() != 6) {
			
			return false;
		}
		
		return true;
	}

	@Override
	public boolean saveConfig(String config) throws IOException, IndexOutOfBoundsException {
		String base = getBase();
		
		if (base == null) {
			logger.error("Unable to get server base directory");
			return false;
		}
		
		File file = new File(base + "/configuration");
		if (file.exists() == false) {
			file.mkdir();
		}
		
		String context = getServletContext().getContextPath();
		
		String confStr = base +"/configuration/" + context + ".properties";
		
		File confFile = new File(confStr);
		
		FileWriter writer = new FileWriter(confFile);
		
		BufferedWriter bWriter = new BufferedWriter(writer);
		
		String[] values = config.split(":");
		
		bWriter.write("DATABASE_TYPE=" + values[0] + "\n");
		bWriter.write("DATABASE_NAME=" + values[1] + "\n");
		bWriter.write("DATABASE_USER=" + values[2] + "\n");
		bWriter.write("DATABASE_PSWD=" + values[3] + "\n");
		bWriter.write("DATABASE_URL="  + values[4] + "\n");
		bWriter.write("DATABASE_PORT=" + values[5] + "\n");
		
		bWriter.flush();
		writer.close();
		
		return true;
	}
	
	private String getBase() {
		String base = System.getProperty("jboss.server.base.dir");
		
		if (base == null) {
			base = System.getProperty("catalina.base");
		}
		
		return base;
	}
}
